package pacman.entries.pacman.ml;

import java.io.*;

import pacman.controllers.Controller;
import pacman.game.Constants.MOVE;
import pacman.game.Game;

/*
 * This is the class you need to modify for your entry. In particular, you need to
 * fill in the getAction() method. Any additional classes you write should either
 * be placed in this package or sub-packages (e.g., game.entries.pacman.mypackage).
 */
public abstract class TrainablePacMan extends Controller<MOVE>
{
	protected boolean trainingMode;
	private String filename;
	
	/*
	 * if training is true, then the controller is in train mode.  learned parameters are saved to the given file name (if one is given)
	 * if training is false, the learned parameters are loaded from the given file
	 */
	public TrainablePacMan(String filename, boolean training) {
		super();
		trainingMode = training;
		this.filename = filename;
		if(trainingMode) {
			InitTraining();
		}
		else if (filename.compareTo("") == 0) {   // no file to load from.  just use default parameters
			InitDefault();
		}
		else {
			try{
				InputStream file = new FileInputStream( filename );
			    InputStream buffer = new BufferedInputStream( file );
			    ObjectInput input = new ObjectInputStream ( buffer );
				InitFromFile(input);
				input.close();
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
			finally {}
		}
	}
	
	protected abstract void InitFromFile(ObjectInput input);
	protected abstract void InitDefault();
	protected abstract void InitTraining();
	protected abstract void TrainingStep();
	protected abstract void CompleteTraining(ObjectOutput output);   // save learned paramters to the file given file
	protected abstract void Complete();    // cleanup function for non-training mode
	public abstract void PrintParameters();
	protected abstract MOVE ChooseMove(Game game);
	
	public boolean isTraining() {
		return trainingMode;
	}
	
	public MOVE getMove(Game game, long timeDue) 
	{
		//Place your game logic here to play the game as Ms Pac-Man
		return ChooseMove(game);
	}
	
	public void UpdateTrainingParameters() {
		if(trainingMode) {
			TrainingStep();
		}
	}
	
	// call this at the end of running games
	public void End() {
		// save parameters to file if training was done, and a file is given
		if(trainingMode && filename.compareTo("") != 0) {
			try {
				OutputStream file = new FileOutputStream(filename);
				OutputStream buffer = new BufferedOutputStream( file );
			    ObjectOutput output = new ObjectOutputStream( buffer );
			    CompleteTraining(output);
			    output.close();
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		else {
			Complete();
		}
	}
	
}